import Utils from "../utils/index";
import Events from '../utils/Events';
// 甘特图校验
class GanttValidate {
   constructor(Gantt) {
      this.Gantt = Gantt;

      // 当前检修时间
      this.repairs = null;
   }

   /**
    * 冲突校验
    */
   validate(repairsReset = true) {
      let points = this.Gantt.timeRange.getCurrentPoints(true);

      /**
       *
       *  {
       * 	'BOF8': [],
       *    'BOF7': [],
       * 	'VD11': [],
       *    'VD12': []
       * }
       */
      this.validateFacilityRepais(repairsReset)


      if (!points) {
         return false;
      }

      this.validatePoints(points);

      this.validateSeries();

      this.finishedValidate(points);
   }

   finishedValidate(points) {
      this.Gantt.timer.addTimeout('redrawChart', 200, () => {
         this.Gantt.chart.redraw();
         for (let key in points) {
            points[key].forEach(p => {
               if (!p || !p.updateConflictStates) {
                  console.log(p);
                  return;
               }
               p.updateConflictStates();
            })
         }
      });
   }


   // 只校验铸机
   validateCCMOnly() {
      let points = this.Gantt.timeRange.getCurrentPoints();
      if (!points) {
         return false;
      }

      let facilityNo = null,
         total = 0,
         facilitPoints = null,
         facility = null,
         ccmPoints = {};
      for (facilityNo in points) {
         facilitPoints = points[facilityNo];
         total = facilitPoints.length;
         if (total === 0) {
            continue;
         }

         facility = Utils.facilities[Math.floor(facilitPoints[0].y)];

         if (facility.facilityType === 'B') {
            ccmPoints[facilityNo] = facilitPoints;
            facilitPoints.forEach(p => {
               p.update({
                  xConflicted: undefined,
                  sConflicted: undefined,
                  cConflicted: undefined,
                  caConflict: undefined,
                  rConflicted: undefined
               }, false);
            });
            // 3、铸机逻辑
            // this.validateCCM(facilitPoints, facilityNo);
         }
      }

      this.finishedValidate(ccmPoints);
   }


   /**
    * 图块校验
    * 1、相同工序之间的图块时间冲突校验
    * 2、检修时间冲突校验
    * 3、铸机校验
    */
   validatePoints(points) {
      if (!points) {
         points = this.Gantt.timeRange.getCurrentPoints();
      }
      let facilityNo = null,
         i = 0,
         j = 0,
         total = 0,
         facilitPoints = null,
         facility = null;

      if (points) {
         for (facilityNo in points) {
            facilitPoints = points[facilityNo];
            total = facilitPoints.length;
            if (total === 0) {
               continue;
            }

            facility = Utils.facilities[Math.floor(facilitPoints[0].y)];

            if (facility.facilityType === 'B') {
               // 3、铸机逻辑
               // this.validateCCM(facilitPoints, facilityNo);
            } else {

               // 1、其他设备逻辑
               for (i = 0; i < total; i++) {
                  if (facilitPoints[i].extra.operationStat !== 'S' && facilitPoints[i].extra.operationStat !== 'I') {
                     continue;
                  }

                  if (i === total - 1) {
                     continue;
                  }

                  for (j = i + 1; j < total; j++) {
                     this.validateTwoPoints(facilitPoints[i], facilitPoints[j]);
                  }
               }
            }
         }

      }
   }

   // 更新图块冲突信息
   updatePointConflict(point, key, conflict, type) {
      let temp = point[type]; // xConflict

      if (!temp) {
         if (!conflict) {
            return false;
         } else {
            temp = {};
         }
      }

      if (!conflict) {
         delete temp[key];
      } else {
         temp[key] = Utils.JSONCopy(conflict)
      }

      let newValue = {};
      newValue[type] = temp;
      point.update(newValue, false);
      // point.updateConflictStates();
   }

   /**
    * 检修时间冲突校验
    */
   validateFacilityRepais(reset) {
      let points = this.Gantt.timeRange.getCurrentPoints(false, true);
      if (points && this.Gantt.chart.repairs) {
         let repairs = this.Gantt.chart.repairs,
            facilityNo = null,
            facilityNoRepairs = null,
            facilitPoints = null,
            conflict = null,
            sid = null,
            repairsMap = {};

         for (sid in repairs) {
            if (!repairsMap[repairs[sid][0]]) {
               repairsMap[repairs[sid][0]] = [];
            }
            repairsMap[repairs[sid][0]].push([repairs[sid][1], repairs[sid][2]]);
         }

         /* repairsMap
           {
         	  'BOF8': [ [开始时间，结束时间], ]
           }

           */



         for (facilityNo in repairsMap) {
            facilityNoRepairs = repairsMap[facilityNo];
            facilitPoints = points[facilityNo];

            if (facilityNoRepairs && facilityNoRepairs.length > 0 && facilitPoints && facilitPoints.length > 0) {
               // 计算交集
               facilityNoRepairs.forEach(repair => {
                  facilitPoints.forEach(point => {
                     conflict = Utils.calcTimeMixed(repair, [point.x, point.x2]);
                     if (conflict) {
                        let existedConflict = point.rConflicted || [];
                        existedConflict.push(conflict);
                        point.update({
                           rConflicted: existedConflict
                        }, false);
                     }
                  });
               })
            };
         }
      }
   }


   //
   validateTwoPoints(point, point1) {
      if (point1.extra.operationStat === 'S' || point1.extra.operationStat === 'I') {
         let xInRagne = point1.x >= point.x && point1.x <= point.x2,
            x2InRange = point1.x2 >= point.x && point1.x2 <= point.x2,
            conflict = null,
            conflictKey = [point.extra.sid, point1.extra.sid],
            sid = null;

         // sid1,sid2 = 冲突
         // 12, 13

         if (conflictKey[0] > point1.extra.sid) {
            sid = conflictKey[0];
            conflictKey[0] = conflictKey[1];
            conflictKey[1] = sid;
         }




         //计算交集
         if (xInRagne || x2InRange) {
            conflict = {
               text: point1.series.options.caId,
               time: []
            }
            conflict.time.push(
               xInRagne ? point1.x : point.x
            );
            conflict.time.push(
               x2InRange ? point1.x2 : point.x2
            );
         }

         this.updatePointConflict(point, conflictKey, conflict, 'xConflicted');
         this.updatePointConflict(point1, conflictKey, conflict, 'xConflicted');
      }
      return false;
   }

   /**
    * 连接线校验
    */
   validateSeries() {
      let series = this.Gantt.timeRange.getCurrentSeries();
      if (series) {
         let i = 0,
            total = 0,
            point = null,
            point1 = null;
         series.forEach(serie => {
            total = serie.points.length;
            if (total === 0) {
               return;
            }
            for (i = 0; i < total - 1; i++) {
               point = serie.points[i];
               point1 = serie.points[i + 1];
               if (point1.extra.operationStat !== 'S' && point1.extra.operationStat !== 'I') {
                  i++;
                  continue;
               }

               if (point.extra.operationStat !== 'S' && point.extra.operationStat !== 'I') {
                  continue;
               }
               this.validateSeriesPoints(point, point1);
            }
         });

      }
   }

   /**
    * 连接线校验
    * @param {Highcharts.Point} point
    * @param {Highcharts.Point} point1
    */
   validateSeriesPoints(point, point1) {
      let configs = this.Gantt.cache.getAll('facilityTimeConfigs', config => {
            return config.startFacilityNo === point.extra.facilityNo &&
               config.endFacilityNo === point1.extra.facilityNo
         }),
         timeConfig = null,
         proccessNo = Utils.facilities[Math.floor(point.y)].proccessNo,
         opTimeConfig = null,
         min = null,
         maxWait = null,
         max = null,
         conflict = null,
         conflictKey = [point.extra.sid, point1.extra.sid],
         sidKey = null;

      if (conflictKey[0] > conflictKey[1]) {
         sidKey = conflictKey[1];
         conflictKey[1] = conflictKey[0];
         conflictKey[0] = sidKey;
      }
      conflictKey = conflictKey.join(',');

      if (configs && configs.length > 0) {
         timeConfig = configs[0];
      }


      let opConfigs = this.Gantt.cache.getAll('operationTimeConfigs', config => {
         return config.proccessNo === proccessNo &&
            config.routeId === point.series.name;
      });

      if (opConfigs && opConfigs.length > 0) {
         opTimeConfig = opConfigs[0];
      }

      min = timeConfig ? timeConfig.minTransTime : null;
      maxWait = opTimeConfig ? opTimeConfig.maxWaitTime : null;
      max = (!min || !maxWait) ? null : min + maxWait;


      if (min !== null || max !== null) {
         let dur = (point1.x - point.x2) / 1000;

         if (min !== null && dur < min) {
            if (!conflict) {
               conflict = {};
            }
            conflict.type = 'min';
         } else if (max !== null && dur > max) {
            if (!conflict) {
               conflict = {};
            }
            conflict.type = 'max';
         }
         if (conflict) {
            conflict.facilities = [Utils.facilities[Math.floor(point.y)].facilityDesc, Utils.facilities[Math.floor(point1.y)].facilityDesc]
         }
      }


      this.updatePointConflict(point, conflictKey, conflict, 'sConflicted');
      this.updatePointConflict(point1, conflictKey, conflict, 'sConflicted');
   }

   /**
    * 铸机校验
    */
   validateCCM(points) {
      let i = 0,
         j = 0,
         total = points.length,
         op = null,
         op1 = null,
         duration = null,
         conflict = null,
         heats = [];

      // 按 lastTime 进行排序
      points = points.sort((a, b) => {
         return a.x2 - b.x2;
      });

      for (; i < total; i++) {
         heats.push(this.Gantt.cache.getById('heats', points[i].extra.heatSid));
      }

      for (i = 0; i < total; i++) {
         op = points[i];
         conflict = null;
         if (i === 0) {
            this.updateCCMPointConflicted(op, conflict);
            continue;
         }
         op1 = null;
         for (j = i - 1; j >= 0; j--) {
            if (heats[j].castSid === heats[i].castSid) {
               op1 = points[j];
               break;
            }
         }

         if (!op1) {
            this.updateCCMPointConflicted(op, conflict);
            continue;
            // j = i - 1;// op2 为 op 的前一个点，直接获取下标即可
         }

         // 钢种冲突
         let caId1 = heats[j].actualCaId || heats[j].caId,
            caId2 = heats[i].actualCaId || heats[i].caId;

         op.update({
            caConflict: caId1 !== caId2 ? [caId1, caId2] : false
         }, false);


         duration = (op.x - op1.x2) / 1000;

         if (duration < -120) { // 发生冲突
            conflict = [op.x, op1.x2];
         } else if (duration > 240) {
            conflict = '浇次中断';
         }

         this.updateCCMPointConflicted(op, conflict);
      }
   }

   updateCCMPointConflicted(point, conflict) {
      point.update({
         cConflicted: conflict
      }, false);
      // point.updateConflictStates();
   }
}

export default GanttValidate;
